sysctl: Return max_node_id rather than nr_nodes from physinfo command.
authorKeir Fraser <keir.fraser@citrix.com>
Wed, 6 Jan 2010 10:13:55 +0000 (10:13 +0000)
committerKeir Fraser <keir.fraser@citrix.com>
Wed, 6 Jan 2010 10:13:55 +0000 (10:13 +0000)
Python extension continues to synthesise a nr_nodes value.

Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
tools/python/xen/lowlevel/xc/xc.c
xen/arch/ia64/xen/dom0_ops.c
xen/arch/x86/sysctl.c
xen/include/public/sysctl.h
xen/include/xen/nodemask.h

index 8a9537e9c4aec5adc36ce6294aaa3cd9131b537c..e7f06d6a9ee2be21db04de6f059fa77943666f63 100644 (file)
@@ -1078,7 +1078,7 @@ static PyObject *pyxc_physinfo(XcObject *self)
 #define MAX_CPU_ID 255
     xc_physinfo_t info;
     char cpu_cap[128], virt_caps[128], *p;
-    int i, j, max_cpu_id;
+    int i, j, max_cpu_id, nr_nodes = 0;
     uint64_t free_heap;
     PyObject *ret_obj, *node_to_cpu_obj, *node_to_memory_obj;
     PyObject *node_to_dma32_mem_obj;
@@ -1105,64 +1105,63 @@ static PyObject *pyxc_physinfo(XcObject *self)
     if ( p != virt_caps )
       *(p-1) = '\0';
 
-    ret_obj = Py_BuildValue("{s:i,s:i,s:i,s:i,s:i,s:l,s:l,s:l,s:i,s:s:s:s}",
-                            "nr_nodes",         info.nr_nodes,
-                            "max_cpu_id",       info.max_cpu_id,
-                            "threads_per_core", info.threads_per_core,
-                            "cores_per_socket", info.cores_per_socket,
-                            "nr_cpus",          info.nr_cpus, 
-                            "total_memory",     pages_to_kib(info.total_pages),
-                            "free_memory",      pages_to_kib(info.free_pages),
-                            "scrub_memory",     pages_to_kib(info.scrub_pages),
-                            "cpu_khz",          info.cpu_khz,
-                            "hw_caps",          cpu_cap,
-                            "virt_caps",        virt_caps);
-
     max_cpu_id = info.max_cpu_id;
     if ( max_cpu_id > MAX_CPU_ID )
         max_cpu_id = MAX_CPU_ID;
 
-    /* Construct node-to-cpu lists. */
+    /* Construct node-to-* lists. */
     node_to_cpu_obj = PyList_New(0);
-
-    /* Make a list for each node. */
-    for ( i = 0; i < info.nr_nodes; i++ )
+    node_to_memory_obj = PyList_New(0);
+    node_to_dma32_mem_obj = PyList_New(0);
+    for ( i = 0; i <= info.max_node_id; i++ )
     {
+        int node_exists = 0;
+        PyObject *pyint;
+
+        /* CPUs. */
         PyObject *cpus = PyList_New(0);
         for ( j = 0; j <= max_cpu_id; j++ )
-            if ( i == map[j]) {
-                PyObject *pyint = PyInt_FromLong(j);
-                PyList_Append(cpus, pyint);
-                Py_DECREF(pyint);
-            }
+        {
+            if ( i != map[j] )
+                continue;
+            pyint = PyInt_FromLong(j);
+            PyList_Append(cpus, pyint);
+            Py_DECREF(pyint);
+            node_exists = 1;
+        }
         PyList_Append(node_to_cpu_obj, cpus); 
         Py_DECREF(cpus);
-    }
-
-    node_to_memory_obj = PyList_New(0);
-
-    for ( i = 0; i < info.nr_nodes; i++ )
-    {
-        PyObject *pyint;
 
+        /* Memory. */
         xc_availheap(self->xc_handle, 0, 0, i, &free_heap);
+        node_exists = node_exists || (free_heap != 0);
         pyint = PyInt_FromLong(free_heap / 1024);
         PyList_Append(node_to_memory_obj, pyint);
         Py_DECREF(pyint);
-    }
 
-    /* DMA memory. */
-    node_to_dma32_mem_obj = PyList_New(0);
-
-    for ( i = 0; i < info.nr_nodes; i++ )
-    {
-        PyObject *pyint;
+        /* DMA memory. */
         xc_availheap(self->xc_handle, 0, 32, i, &free_heap);
         pyint = PyInt_FromLong(free_heap / 1024);
         PyList_Append(node_to_dma32_mem_obj, pyint);
         Py_DECREF(pyint);
+
+        if ( node_exists )
+            nr_nodes++;
     }
 
+    ret_obj = Py_BuildValue("{s:i,s:i,s:i,s:i,s:i,s:l,s:l,s:l,s:i,s:s:s:s}",
+                            "nr_nodes",         nr_nodes,
+                            "max_node_id",      info.max_node_id,
+                            "max_cpu_id",       info.max_cpu_id,
+                            "threads_per_core", info.threads_per_core,
+                            "cores_per_socket", info.cores_per_socket,
+                            "nr_cpus",          info.nr_cpus, 
+                            "total_memory",     pages_to_kib(info.total_pages),
+                            "free_memory",      pages_to_kib(info.free_pages),
+                            "scrub_memory",     pages_to_kib(info.scrub_pages),
+                            "cpu_khz",          info.cpu_khz,
+                            "hw_caps",          cpu_cap,
+                            "virt_caps",        virt_caps);
     PyDict_SetItemString(ret_obj, "node_to_cpu", node_to_cpu_obj);
     Py_DECREF(node_to_cpu_obj);
     PyDict_SetItemString(ret_obj, "node_to_memory", node_to_memory_obj);
index d5a971e84b7fe604e0df708ba40dcddbe11ecb87..5c521c96cb35ebb5c72a8f5f340aa2e5b733691a 100644 (file)
@@ -715,12 +715,12 @@ long arch_do_sysctl(xen_sysctl_t *op, XEN_GUEST_HANDLE(xen_sysctl_t) u_sysctl)
         pi->cores_per_socket =
             cpus_weight(per_cpu(cpu_core_map, 0)) / pi->threads_per_core;
         pi->nr_cpus          = (u32)num_online_cpus();
-        pi->nr_nodes         = num_online_nodes();
         pi->total_pages      = total_pages; 
         pi->free_pages       = avail_domheap_pages();
         pi->scrub_pages      = 0;
         pi->cpu_khz          = local_cpu_data->proc_freq / 1000;
 
+        pi->max_node_id = last_node(node_online_map);
         pi->max_cpu_id = last_cpu(cpu_online_map);
         max_array_ent = min_t(uint32_t, max_array_ent, pi->max_cpu_id);
 
index 27bda34e6e7def7abb6bbe5323c921fc544b65af..c08cb3d4bdc7461c5e5b0322fd9fb448aae6b50b 100644 (file)
@@ -64,7 +64,6 @@ long arch_do_sysctl(
         pi->cores_per_socket =
             cpus_weight(per_cpu(cpu_core_map, 0)) / pi->threads_per_core;
         pi->nr_cpus = (u32)num_online_cpus();
-        pi->nr_nodes = num_online_nodes();
         pi->total_pages = total_pages;
         pi->free_pages = avail_domheap_pages();
         pi->scrub_pages = 0;
@@ -75,6 +74,7 @@ long arch_do_sysctl(
         if ( iommu_enabled )
             pi->capabilities |= XEN_SYSCTL_PHYSCAP_hvm_directio;
 
+        pi->max_node_id = last_node(node_online_map);
         pi->max_cpu_id = last_cpu(cpu_online_map);
         max_array_ent = min_t(uint32_t, max_array_ent, pi->max_cpu_id);
 
index 926eaf183efc9e1e0b4a3cb1fa68a99fbe2cf2b1..f869f9c5afddf5d0d00919be068b6dda89f207cd 100644 (file)
@@ -34,7 +34,7 @@
 #include "xen.h"
 #include "domctl.h"
 
-#define XEN_SYSCTL_INTERFACE_VERSION 0x00000006
+#define XEN_SYSCTL_INTERFACE_VERSION 0x00000007
 
 /*
  * Read console content from Xen buffer ring.
@@ -94,7 +94,7 @@ struct xen_sysctl_physinfo {
     uint32_t threads_per_core;
     uint32_t cores_per_socket;
     uint32_t nr_cpus;
-    uint32_t nr_nodes;
+    uint32_t max_node_id;
     uint32_t cpu_khz;
     uint64_aligned_t total_pages;
     uint64_aligned_t free_pages;
index 30ed6f45245fdb194eb3186ccfbb85cdbf97b65c..84ebfa95ad74a15446fcff962dbe1ef8b641a26c 100644 (file)
@@ -38,6 +38,7 @@
  *
  * int first_node(mask)                        Number lowest set bit, or MAX_NUMNODES
  * int next_node(node, mask)           Next node past 'node', or MAX_NUMNODES
+ * int last_node(mask)                 Number highest set bit, or MAX_NUMNODES
  * int first_unset_node(mask)          First node not set in mask, or 
  *                                     MAX_NUMNODES.
  *
@@ -214,16 +215,27 @@ static inline void __nodes_shift_left(nodemask_t *dstp,
 /* FIXME: better would be to fix all architectures to never return
           > MAX_NUMNODES, then the silly min_ts could be dropped. */
 
-#define first_node(src) __first_node(&(src))
-static inline int __first_node(const nodemask_t *srcp)
+#define first_node(src) __first_node(&(src), MAX_NUMNODES)
+static inline int __first_node(const nodemask_t *srcp, int nbits)
 {
-       return min_t(int, MAX_NUMNODES, find_first_bit(srcp->bits, MAX_NUMNODES));
+       return min_t(int, nbits, find_first_bit(srcp->bits, nbits));
 }
 
-#define next_node(n, src) __next_node((n), &(src))
-static inline int __next_node(int n, const nodemask_t *srcp)
+#define next_node(n, src) __next_node((n), &(src), MAX_NUMNODES)
+static inline int __next_node(int n, const nodemask_t *srcp, int nbits)
 {
-       return min_t(int,MAX_NUMNODES,find_next_bit(srcp->bits, MAX_NUMNODES, n+1));
+       return min_t(int, nbits, find_next_bit(srcp->bits, nbits, n+1));
+}
+
+#define last_node(src) __last_node(&(src), MAX_NUMNODES)
+static inline int __last_node(const nodemask_t *srcp, int nbits)
+{
+       int node, pnode = nbits;
+       for (node = __first_node(srcp, nbits);
+            node < nbits;
+            node = __next_node(node, srcp, nbits))
+               pnode = node;
+       return pnode;
 }
 
 #define nodemask_of_node(node)                                         \